#include "Mapa.h"
#include "Territorio.h"
#include "CartaDeObjetivos.h"
#include <iostream>
using namespace std;

Mapa::Mapa(FabricaDeTerritorios* fabricaDeTerritorios)
{
	this->fabricaDeTerritorios = fabricaDeTerritorios;
	this->cantidadDeTerritorios = 0;
}

void Mapa :: update(Observable *observable){
	notifyObservers();
}

unsigned int Mapa::getContinentesEnPoderDeJugador(string colorJugador) {
	unsigned int resultado = 0;
	for (map<string,Continente*>::iterator it = continentes.begin(); it != continentes.end(); it++)
			if (it->second->enPoderDeJugador(colorJugador))
				resultado++;
	return resultado;
}

unsigned int Mapa::getTerritoriosEnPoderDeJugador(string colorJugador) {
	unsigned int resultado = 0;
	for (map<string,Continente*>::iterator it = continentes.begin(); it != continentes.end(); it++)
			resultado += it->second->getCantidadDeTerritoriosEnPoderDeJugador(colorJugador);
	return resultado;
}

Territorio* Mapa::obtenerTerritorio(string nombre) {
	Territorio* aux = NULL;
	for (map<string,Continente*>::iterator it = continentes.begin(); it != continentes.end(); it++)
		if (it->second->getTerritorio(nombre) != NULL)
			aux = it->second->getTerritorio(nombre);
	return aux;
}

Continente* Mapa::obtenerContinente(string nombre) {
	if (continentes.count(nombre) == 1)
		return continentes[nombre];
	else
		return NULL;
}

map<string,Continente*>* Mapa::obtenerContinentes() {
	return &continentes;
}

void Mapa::agregarContinente(string nombre, int bonus) {
	continentes[nombre] = new Continente(nombre,bonus);
}

void Mapa::agregarContinente(string nombre) {
	continentes[nombre] = new Continente(nombre);
}

void Mapa::agregarTerritorio(string nombre, int x, int y, string continente) {
	Continente* aux = continentes[continente];
	Territorio *t = fabricaDeTerritorios->crearTerritorio(nombre,x,y,aux);
	t->addObserver(this);
	aux->agregarTerritorio(t);
	cantidadDeTerritorios++;
}

void Mapa::quitarContinente(std::string nombre) {
	continentes.erase(nombre);
}

bool Mapa::sonAdyacentes(Territorio* unTerritorio, Territorio* otroTerritorio) {
	return unTerritorio->obtenerTerritoriosAdyacentes()->count(otroTerritorio->getNombre());
}

bool Mapa::todosLosTerritoriosConEjercitos() {
	for (map<string,Continente*>::iterator it = continentes.begin(); it != continentes.end(); it++)
		if (!it->second->todosLosTerritoriosConEjercitos())
			return false;
	return true;
}

void Mapa::imprimirEstado() {
	cout<<"Estado del Mapa"<<endl<<endl;
	for (map<string,Continente*>::iterator it = continentes.begin(); it != continentes.end(); it++) {
		cout<<"Continente:"<<it->second->getNombre()<<endl;
		for (map<string,Territorio*>::iterator ite = it->second->getTerritorios()->begin(); ite != it->second->getTerritorios()->end(); ite++)
			cout<<"		Territorio:"<<ite->second->getNombre()<<" En poder de: "<<ite->second->getEnPoderDe()<<" Ejercitos: "<<ite->second->getCantidadDeEjercitos()<<endl;
		cout<<endl;
	}
	
}

int Mapa::getCantidadDeTerritorios() {
	return this->cantidadDeTerritorios;
}

int Mapa::getCantidadDeCartas() {
	return this->cartasDeObjetivos.size();
}

void Mapa::agregarCartaDeObjetivos(CartaDeObjetivos* cartaDeObjetivos) {
	this->cartasDeObjetivos.push_back(cartaDeObjetivos);
}

CartaDeObjetivos* Mapa::obtenerCarta(unsigned int numero) {
	if (numero < cartasDeObjetivos.size())
		return cartasDeObjetivos[numero];
	else
		return NULL;
}

Mapa::~Mapa()
{
	map<string,Continente*>::iterator it = continentes.begin();
	
	while(continentes.size() != 0){
		Continente* c = (*it).second;
		delete (c);
		continentes.erase(it);
		it = continentes.begin();
	}
}
